package com.wonders.frame.chron.controller.config;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.wonders.frame.chron.model.bo.Catalog;
import com.wonders.frame.chron.service.catalog.CatalogService;
import com.wonders.frame.chron.util.ConstantUtil;
import com.wonders.frame.core.controller.AbstractSingleCrudieController;
import com.wonders.frame.core.dao.RelationDao;
import com.wonders.frame.core.model.IDefaultModel;
import com.wonders.frame.core.model.bo.ImportConfig;
import com.wonders.frame.core.model.bo.ImportConfigLog;
import com.wonders.frame.core.model.bo.Relation;
import com.wonders.frame.core.model.vo.FieldProperty;
import com.wonders.frame.core.model.vo.ObjectInfoVo;
import com.wonders.frame.core.model.vo.ReturnObj;
import com.wonders.frame.core.model.vo.SingleQueryParams;
import com.wonders.frame.core.service.BasicCrudService;
import com.wonders.frame.core.service.ImportConfigService;
import com.wonders.frame.core.service.ObjInfoCache;
import com.wonders.frame.core.tags.ShowInView;
import com.wonders.frame.core.utils.DateFormatUtil;
import com.wonders.frame.core.utils.ExcelUtil;
import com.wonders.frame.core.utils.ReflectUtil;

@Controller
@RequestMapping("/api/importConfig")
public class importConfigController extends AbstractSingleCrudieController<Catalog>{
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	@Override
	public String getExcelExportField(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Autowired	
	private ImportConfigService importConfigService;
	
	@Autowired	
	private CatalogService catalogService ;
	
	@Autowired	
	private BasicCrudService basicCrudService;
	
	@Autowired
	private RelationDao relationDao;
	
	@RequestMapping(value="/importCatalog", method = RequestMethod.POST)
	@ResponseBody
	public synchronized ReturnObj<HashMap<String, Object>> importCatalog(@RequestParam("type") String type,@RequestParam("catalogType") String catalogType,@RequestParam("resourceType") String resourceType,HttpServletRequest request) {
		HashMap<String,Object> importResult=new HashMap<String,Object>();
		try {
			MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
			Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
			// 文件保存路径
			String savePath = request.getSession().getServletContext().getRealPath("/")+ "uploadFiles";
			savePath += File.separator + DateFormatUtil.getCurrentDate()+ File.separator;
			// 创建文件夹
			File file = new File(savePath);
			if (!file.exists()) {
				file.mkdirs();
			}
			for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
				// 上传文件
				MultipartFile mf = entity.getValue();
				// 获取文件后缀
				String ext = mf.getOriginalFilename().substring(mf.getOriginalFilename().lastIndexOf("."));
				// 重命名文件
				String newFileName = DateFormatUtil.getFileDateTime() + "_"+ new Random().nextInt(1000) + ext;
				File uploadFile = new File(savePath + newFileName);
				FileCopyUtils.copy(mf.getBytes(), uploadFile);

				// 创建导入Excel数据操作日志对象
				ImportConfigLog importLog = new ImportConfigLog();
				importLog.setOriginalFilename(mf.getOriginalFilename().substring(0,mf.getOriginalFilename().lastIndexOf(".")));
				importLog.setSaveFilename(newFileName.substring(0,newFileName.lastIndexOf(".")));
				importLog.setFileType(ext);
				importLog.setSavePath(savePath);
				importLog.setImportTime(new Date(System.currentTimeMillis()));
				if (mf != null) {
					List<Object> datas = importData(uploadFile,type,request);
					for (Object o : datas) {
						Catalog c=(Catalog)o;

						//得到code
						String[] codes = StringUtils.split(c.getParentCode(),"-");
						c.setCode(codes[codes.length-1]);
						c.setType(catalogType);
						c.setResourceType(resourceType);
						//得到parent节点 code
						HashMap<String, String> map=new HashMap<String, String>();
						//判断节点是否为根节点
						if (!"1".equals(c.getProperty())) {
							String parentCode=c.getParentCode().substring(0, c.getParentCode().lastIndexOf("-"));
							SingleQueryParams sqp = new SingleQueryParams(getEntityClass());
							sqp.addData("property", (Integer.parseInt(c.getProperty())-1)+"");
							sqp.addData("type", catalogType);
							sqp.addData("resourceType", resourceType);
							sqp.addData("parentCode",parentCode);
							catalogService.save(c);
							ReturnObj<List<IDefaultModel>> obj = basicCrudService.find(sqp);
							
							if(!obj.getInfo().getSuccess() || obj.getData().size()<1)
								continue;
							
							Catalog pCatalog=(Catalog) obj.getData().get(0);
							//绑定关系
							Relation r=new Relation(getEntityName(), pCatalog.getId(), getEntityName(), c.getId(),1);
							relationDao.save(r);
						}else{
							catalogService.save(c);
							Relation r=new Relation(getEntityName(), ConstantUtil.CATALOG_ROOT_ID, getEntityName(), c.getId(),1);
							relationDao.save(r);
						}
					}
					if (datas != null) {// 文件导入数据成功
						importLog.setFlag("true");
						importLog.setRecordNum(datas.size());
						importResult.put(mf.getOriginalFilename(),datas);
					} else {// 文件导入数据失败
						importLog.setFlag("false");
						importLog.setRecordNum(0);
						importResult.put(mf.getOriginalFilename(),null);
					}
					// 保存本次导入Excel数据操作日志
					importLog=importConfigService.saveLog(importLog);
				}
			}
			return new ReturnObj<HashMap<String,Object>>(importResult);
		} catch (Exception e) {
			return new ReturnObj<HashMap<String,Object>>(e);
		}
	}
	
	@Override
	public List<Object> importData(File file, String type,HttpServletRequest request) {
		Long start = System.currentTimeMillis();
		List<Object> datas = new ArrayList<Object>();
		List<String[]> list = ExcelUtil.getExcelData(file);
		if (list == null || list.size() < 1) {
			return datas;
		}
		try {
			ObjectInfoVo objectInfo=ObjInfoCache.getObjectInfo(getEntityClass());
			Class<?> crudObjClazz = objectInfo.getClazz();
			// 根据type、实体对象查询Excel导入数据配置项
			List<ImportConfig> queryObj=importConfigService.findByEntityAndType(getEntityName(), type);
//			List<ImportConfig> queryObj = (List<ImportConfig>) ReflectUtil.executeMethod("importConfig", "findByEntityAndType",
//					new Class[] { String.class,String.class }, new Object[] { getEntityName(),type });
			if (queryObj == null) {
				return null;
			}
			// 根据type查询Excel导入数据配置，该配置下的Excel只能是存在标题、不存在标题其中一种
			// 判断是否存在标题
			Integer hasTitle = (queryObj.get(0)).getHasTitle();
			if (hasTitle == 1) {// 存在标题
				for (int i = 1; i < list.size(); i++) {
					boolean isEmpty=isNotEmpty(list.get(i));
					if(isEmpty){
						continue;
					}
					Object obj = crudObjClazz.newInstance();
					for (int j = 0; j < queryObj.size(); j++) {
						String entityField = (String) ReflectUtil.invokeGet(queryObj.get(j), "entityField");
						String excelField = (String) ReflectUtil.invokeGet(queryObj.get(j), "excelField");
						// 遍历标题集合
						int flag = 0;
						for (int k = 0; k < list.get(0).length; k++) {
							if (excelField.equals(list.get(0)[k])) {
								flag = k;
								break;
							}
						}
						if (!"".equals(list.get(i)[flag])) {
							Field field = crudObjClazz.getDeclaredField(entityField);
							String fieldExcelData = list.get(i)[flag];
							setData(type,field ,fieldExcelData,entityField,crudObjClazz,obj);
						}
					}
					//ReflectUtil.executeMethod(getEntityClass(), "save",new Class[] { Object.class }, new Object[] { obj });
					datas.add(obj);
				}
			} else {// 不存在标题,配置中列必须从1开始
				for (int i = 0; i < list.size(); i++) {
					
					boolean isEmpty=isNotEmpty(list.get(i));
					if(isEmpty){
						continue;
					}
					Object obj = crudObjClazz.newInstance();
					for (int j = 0; j < queryObj.size(); j++) {
						String entityField = (String) ReflectUtil.invokeGet(queryObj.get(j), "entityField");
						String excelField = (String) ReflectUtil.invokeGet(queryObj.get(j), "excelField");
                        Integer column=Integer.valueOf(excelField);
						if (!list.get(i)[column - 1].equals("")) {
							Field field = crudObjClazz.getDeclaredField(entityField);
							String fieldExcelData = list.get(i)[column - 1];
							setData(type,field ,fieldExcelData,entityField,crudObjClazz,obj);
						}
					}
					datas.add(obj);
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.debug("error", e);
		}
		logger.debug("[import]--Owner total：" + datas.size());
		logger.debug("[import]--parse excel use time:"+ (System.currentTimeMillis() - start) + " ms");
		return datas;
	}
	/**
	 * 判断Excel当前行是否是空行
	 * @param obj
	 * @return
	 */
	private boolean isNotEmpty(Object[] obj){
		int length=0;
		for(int m=0;m<obj.length;m++){
			if(obj[m]==null||"".equals(obj[m])){
				length++;
			}
		}
		if(length==obj.length){
			return true;//空行
		}else{
			return false;//非空行
		}
	}
	
	/**
	 * @author taoweiwei
	 * 给指定对象的指定字段设置Excel数据
	 * @param field
	 * @param fieldExcelData
	 * @param entityField
	 * @param crudObjClazz
	 * @param obj
	 */
	@SuppressWarnings("unused")
	private void setData(String type,Field field ,String fieldExcelData,String entityField,Class<?> crudObjClazz,Object obj){
		/**
		 * 判断该字段上是否存在ShowInView注解，
		 * 一、存在该注解，则判断该选项是否是字典项（即是否是一个选择项）；
		 * 1、若是一个字典项，则取出其字典项，找 出excel中数据对应的字典项code保存到数据库；
		 * 2、若不是一个字典项，则将excel中数据值保存到数据库
		 * 二、不存在该注解，则将excel中值存到数据库
		 */

		ShowInView showInView = field.getAnnotation(ShowInView.class);
		if (showInView != null) {// 存在ShowInView注解
			String ccateType = showInView.ccateType();
			if (!"".equals(ccateType)) {// 存在字典项
				List<FieldProperty> fieldProperties = ReflectUtil.getFieldProperties(crudObjClazz,field.getName(), true);
				FieldProperty fieldProperty = fieldProperties.get(0);
				LinkedHashMap<String,String> option = fieldProperty.getOption();
				HashMap<String,LinkedHashMap<String,String>> code=fieldProperty.getCodes();
				fieldExcelData=convertExcelImportData(type,entityField ,fieldExcelData,option,code);
			}else{
				fieldExcelData=convertExcelImportData(type,entityField ,fieldExcelData,null,null);
			}
		}
		
		String returnType = field.getType().getName().toString();
		if (returnType.contains("Long")) {
			ReflectUtil.invokeSet(obj, entityField,Long.valueOf(fieldExcelData));
		} else if (returnType.contains("Integer")) {
			ReflectUtil.invokeSet(obj, entityField,Integer.valueOf(fieldExcelData));
		} else if (returnType.contains("Date")) {
			ReflectUtil.invokeSet(obj, entityField,DateFormatUtil.timeParse("yyyy-MM-dd HH:mm:ss",fieldExcelData));
		} else if (returnType.contains("Double")) {
			ReflectUtil.invokeSet(obj, entityField,Double.valueOf(fieldExcelData));
		} else if (returnType.contains("Float")) {
			ReflectUtil.invokeSet(obj, entityField,Float.valueOf(fieldExcelData));
		} else if (returnType.contains("Boolean")) {
			ReflectUtil.invokeSet(obj, entityField,Boolean.valueOf(fieldExcelData));
		} else {
			ReflectUtil.invokeSet(obj, entityField,fieldExcelData);
		}
	}
}
